package com.audaque.springboot.foshanupload.web.webdemo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.audaque.springboot.foshanupload.log.anno.WebLogAnno;
import com.audaque.springboot.foshanupload.web.webdemo.model.domain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping(value = "/fastjson")
public class FastJsonController {

    private static Student s=new Student();

    static {
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("1");
        OuterClass outerClass = new OuterClass();
        outerClass.setOuterVar(1);
        employee.setOuterClass(outerClass);
        s.setName("5wimming");
        s.setSex(2);
        Monitor monitor = null;
        try {
            monitor = new Monitor();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        monitor.setEmployee(employee);
        s.setMyObject(monitor);
        s.setMonitor(monitor);
        s.setEmployee(employee);

        Person person = new Person();
        person.setDescribe("1");
        person.setId("1");
        person.setName("1");
        person.setAge(1);
        person.setHeight(1);
        Country country = new Country();
        country.setId("1");
        country.setName("1");
        person.setPersonCountry(country);



        Person person2 = new Person();
        person2.setDescribe("2");
        person2.setId("2");
        person2.setName("2");
        person2.setAge(2);
        person2.setHeight(2);
        Country country2 = new Country();
        country2.setId("2");
        country2.setName("2");
        person2.setPersonCountry(country2);

        List<Person> personList = new ArrayList<>();
        personList.add(person);
        personList.add(person2);

        s.setPersonList(personList);


    }

    @WebLogAnno
    @GetMapping("/toJsonStr")
    public String toJsonStr() throws Exception {
        return JSON.toJSONString(s);
    }

    @WebLogAnno
    @GetMapping("/parse")
    public Student parse() throws Exception {
        return JSON.parseObject(toJsonStr(), Student.class);
    }

    @WebLogAnno
    @GetMapping("/test1")
    public void test1() throws Exception {
        String jsonString1 = JSON.toJSONString(s, SerializerFeature.WriteMapNullValue);
        String jsonString2 = JSON.toJSONString(s, SerializerFeature.PrettyFormat);
        String jsonString3 = JSON.toJSONString(s, SerializerFeature.SkipTransientField);
        String jsonString4 = JSON.toJSONString(s, SerializerFeature.WriteClassName);

        log.info("jsonString1:" + jsonString1);
        log.info("jsonString2:" + jsonString2);
        log.info("jsonString3:" + jsonString3);
        log.info("jsonString4:" + jsonString4);

        Student students1 = JSON.parseObject(jsonString1, Student.class);
        Student students2 = JSON.parseObject(jsonString2, Student.class);
        Student students3 = JSON.parseObject(jsonString3, Student.class);
        Object students4 = JSON.parse(jsonString4);
        log.info("finish");
    }


    @WebLogAnno
    @GetMapping("/toJsonStr2")
    public String toJsonStr2() throws Exception {
        List<Student> list = new ArrayList<>();
        list.add(s);
        return JSON.toJSONString(list);
    }

    @WebLogAnno
    @GetMapping("/parse2")
    public List<Student> parse2() throws Exception {
        return JSON.parseArray(toJsonStr2(), Student.class);
    }

    @WebLogAnno
    @GetMapping("/toJsonStr3")
    public String toJsonStr3() throws Exception {
        return JSON.toJSONStringWithDateFormat(s, "yyyy-MM-dd");
    }

    @WebLogAnno
    @GetMapping("/parse3")
    public Student parse3() throws Exception {
        return JSON.parseObject(toJsonStr3(), Student.class);
    }

    @WebLogAnno
    @GetMapping("/toJsonStr4")
    public String toJsonStr4() throws Exception {
        ValueFilter filter = (object, name, value) -> {
            if (name.equals("age")) {
                return null; // 不包括 "age" 字段
            }
            return value;
        };
        return JSON.toJSONString(s, filter);
    }

    @WebLogAnno
    @GetMapping("/parse4")
    public Student parse4() throws Exception {
        return JSON.parseObject(toJsonStr4(), Student.class);
    }

    /**
     * 从v1.2.25开始
     * @return
     * @throws IOException
     */
/*


    @WebLogAnno
    @GetMapping("/toJsonStr5")
    public String toJsonStr5() throws Exception {
        return JSON.toJSONString(s, SerializerFeature.WriteClassName);
    }



    @WebLogAnno
    @GetMapping("/parse51")
    public Object parse51() throws Exception {
        // 创建ParserConfig实例,全局生效，不可重置
        ParserConfig parserConfig = new ParserConfig();
        // 开启autoType功能
        parserConfig.setAutoTypeSupport(true);
        // 在这里进行JSON的反序列化操作，Fastjson会根据JSON字符串中的@type信息自动选择对应的类型
        Object result = JSON.parse(toJsonStr5(),parserConfig);
        return result;
    }

    @WebLogAnno
    @GetMapping("/parse511")
    public Object parse511() throws Exception {
        // 创建ParserConfig实例,全局生效，不可重置
        ParserConfig parserConfig= new ParserConfig();
        // 开启autoType功能
        parserConfig.setAutoTypeSupport(true);
        //黑名单
        parserConfig.addDeny("com.audaque.springboot.foshanupload.web.webdemo.model.domain.Student");
        // 在这里进行JSON的反序列化操作，Fastjson会根据JSON字符串中的@type信息自动选择对应的类型
        Object result = JSON.parse(toJsonStr5(),parserConfig);
        return result;
    }

    @WebLogAnno
    @GetMapping("/parse52")
    public Object parse52() throws Exception {
        // 创建ParserConfig实例,全局生效，不可重置
        ParserConfig parserConfig = new ParserConfig();
        // 关闭autoType功能
        parserConfig.setAutoTypeSupport(false);
        // 在这里进行JSON的反序列化操作，Fastjson会根据JSON字符串中的@type信息自动选择对应的类型
        Object result = JSON.parse(toJsonStr5(),parserConfig);
        return result;
    }



    @WebLogAnno
    @GetMapping("/parse521")
    public Object parse521() throws Exception {
        // 创建ParserConfig实例,全局生效，不可重置
        ParserConfig parserConfig = new ParserConfig();
        // 关闭autoType功能
        parserConfig.setAutoTypeSupport(false);
        //引入 checkAutoType 安全机制，从v1.2.25开始，fastjson默认关闭了autotype支持，并且加入了checkAutotype，加入了黑名单+白名单来防御autotype开启的情况
        //安全更新主要集中在com.alibaba.fastjson.parser.ParserConfig，首先查看类上出现了几个成员变量：布尔型的 autoTypeSupport，用来标识是否开启任意类型的反序列化，并且默认关闭；字符串数组 denyList ，是反序列化类的黑名单；acceptList 是反序列化白名单。
        // 白名单：设置允许的类型，以防止autoType攻击
        parserConfig.addAccept("abc");
        // 在这里进行JSON的反序列化操作，Fastjson会根据JSON字符串中的@type信息自动选择对应的类型
        Object result = JSON.parse(toJsonStr5(),parserConfig);
        return result;
    }



    @WebLogAnno
    @GetMapping("/parse522")
    public Object parse522() throws Exception {
        // 创建ParserConfig实例,全局生效，不可重置
        ParserConfig parserConfig = new ParserConfig();
        // 关闭autoType功能
        parserConfig.setAutoTypeSupport(false);
        //引入 checkAutoType 安全机制，从v1.2.25开始，fastjson默认关闭了autotype支持，并且加入了checkAutotype，加入了黑名单+白名单来防御autotype开启的情况
        //安全更新主要集中在com.alibaba.fastjson.parser.ParserConfig，首先查看类上出现了几个成员变量：布尔型的 autoTypeSupport，用来标识是否开启任意类型的反序列化，并且默认关闭；字符串数组 denyList ，是反序列化类的黑名单；acceptList 是反序列化白名单。
        // 白名单：设置允许的类型，以防止autoType攻击
        parserConfig.addAccept("com.audaque.springboot.foshanupload.web.webdemo.model.domain.Student");
        // 在这里进行JSON的反序列化操作，Fastjson会根据JSON字符串中的@type信息自动选择对应的类型
        Object result = JSON.parse(toJsonStr5(),parserConfig);
        return result;
    }



    @WebLogAnno
    @GetMapping("/parse523")
    public Object parse523() throws Exception {
        // 创建ParserConfig实例,全局生效，不可重置
        ParserConfig parserConfig = new ParserConfig();
        // 关闭autoType功能
        parserConfig.setAutoTypeSupport(false);
        //引入 checkAutoType 安全机制，从v1.2.25开始，fastjson默认关闭了autotype支持，并且加入了checkAutotype，加入了黑名单+白名单来防御autotype开启的情况
        //安全更新主要集中在com.alibaba.fastjson.parser.ParserConfig，首先查看类上出现了几个成员变量：布尔型的 autoTypeSupport，用来标识是否开启任意类型的反序列化，并且默认关闭；字符串数组 denyList ，是反序列化类的黑名单；acceptList 是反序列化白名单。
        // 黑名单
        parserConfig.addDeny("com.audaque.springboot.foshanupload.web.webdemo.model.domain.Student");
        // 在这里进行JSON的反序列化操作，Fastjson会根据JSON字符串中的@type信息自动选择对应的类型
        Object result = JSON.parse(toJsonStr5(),parserConfig);
        return result;
    }

*/




    @WebLogAnno
    @GetMapping("/jsonSerialize")
    public byte[] jsonSerialize() throws IOException {
        //java和springboot网络传输底层序列化类
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        SerializeWriter out = new SerializeWriter(SerializerFeature.WriteClassName);
        JSONSerializer serializer = new JSONSerializer(out);
        serializer.write(s);
        out.writeTo(os, "UTF-8");
        return os.toByteArray();
    }

    @WebLogAnno
    @GetMapping("/javaSerialize")
    public byte[] javaSerialize() throws IOException {
        //java和springboot网络传输底层序列化类
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(s);
        return os.toByteArray();
    }

    @WebLogAnno
    @GetMapping("/jsonDeserialize")
    private Student jsonDeserialize() throws IOException {
        return JSON.parseObject(jsonSerialize(), Student.class);
    }

    @WebLogAnno
    @GetMapping("/javaDeserialize")
    private Student javaDeserialize() throws IOException, ClassNotFoundException {
        ByteArrayInputStream is = new ByteArrayInputStream(javaSerialize());
        ObjectInputStream ois = new ObjectInputStream(is);
        return (Student) ois.readObject();
    }








}